package comp9417;

import java.io.Console;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Created by huy on 3/06/14.
 */
public class FindBestFold {

    private Console console;
    private int minK = 2;
    private int maxK = 10;
    //private int folds = 10;
    private boolean weighted = false;

    public FindBestFold(Console console) {
        this.console = console;
    }

    public static void main(String[] args) throws FileNotFoundException {
        Console console = System.console();
        if (console == null) {
            System.out.println("Cannot start console.");
            System.exit(0);
        }
        FindBestFold evaluation = new FindBestFold(console);
        evaluation.go();
    }

    private void go() throws FileNotFoundException {
        int option = 1;
        Dataset dataset = null;
        Evaluator evaluator = null;
        int[] maxKforFold;
        List<String> filesName = new LinkedList<String>();
        while (option > 0) {
            if (option <= 1) {
                console.printf("Enter Folder:");
                String folderAdd = console.readLine();
                File folder = new File(folderAdd);
                File[] listOfFiles = folder.listFiles();
                
                for ( int i = 0 ; i < listOfFiles.length; i++){
                	File file = listOfFiles[i];
                	if(file.isFile() && file.getName().endsWith((".arff"))){
                		filesName.add(folderAdd + "/" + file.getName());
                	}
                	
                }
                
                minK = parseInteger("Enter minimum k [%d]:", minK);
                console.printf("User picked: %d\n", minK);
                maxK = parseInteger("Enter maximum k [%d]:", maxK);
                console.printf("User picked: %d\n", maxK);
               //folds = parseInteger("Enter number of folds [%d]:", folds);
               //console.printf("User picked: %d\n", folds);
                weighted = parseBoolean("Use weighted distance [%b]:", weighted);
                console.printf("User picked: %b\n", weighted);
                
                
            //    dataset = new DataLoader().loadClassificationData(fileName);
            }
            
            // bestKlist[fold][k];
            int[][] bestKList = new int[maxK+1][maxK+1];
            maxKforFold = new int[maxK+1];
            //int tempMax;
            int bestkTempValue;
            for( int fold = 1 ; fold <= maxK ; fold++){
	            //bestkTemp = -1;
            	for( String fn : filesName){
	            	console.printf("loading %s\n", fn);
	                dataset = new DataLoader().loadClassificationData(fn);
	                String lastAttribute = dataset.getAttributes()[dataset.getAttributes().length -1].name;
	                evaluator = new Evaluator(dataset, lastAttribute);
	                //evaluator.bestK(minK, maxK, folds, weighted);
	                /*
		            if (option <= 2) {
		                console.printf("Loaded dataset with %d datapoints. The followings are the attributes found: \n", dataset.getDatapoints().size());
		                for (Attribute attribute : dataset.getAttributes()) {
		                    console.printf("%s\n", attribute.name);
		                }
		                console.printf("Enter attribute to predict/classify:");
		                String attribute = console.readLine();
		                evaluator = new Evaluator(dataset, attribute);
		            }*/
		            if (option <= 3) {
		            	bestkTempValue = evaluator.bestK(minK, maxK,fold,weighted);
		            	bestKList[fold][bestkTempValue]++;
		                console.printf("%2d ",bestkTempValue);
		                /*console.printf("Statistic: \n");
		                console.printf("k | Error\n");
		                for (Map.Entry<Integer, Double> entry : evaluator.getStats().entrySet()) {
		                    console.printf("%2d | %f\n", entry.getKey(), entry.getValue());
		                }
		                */
		            }
	
	            
	            }
	            console.printf("\n");
            }
            console.printf("fold | k | num\n ");
            
            for (int fold = 1 ; fold<= maxK ; fold++){
            	bestkTempValue  = -1;
            	//console.printf("============\n");
            	for( int k = 1 ; k <= maxK ; k++){
            		if (bestKList[fold][k] >= bestkTempValue){
            			bestkTempValue= bestKList[fold][k];
            			maxKforFold[fold] = k;
            		}
            		console.printf("%d, %d,  %d\n",fold, k, bestKList[fold][k]);
            	}
            }
            
            console.printf("fold  | best K\n============\n");
            for ( int fold = 1 ; fold <= maxK ; fold++){
            	console.printf("%d    |  %d\n", fold, maxKforFold[fold]);
            	
            }
            

            
            option = parseInteger("Do you want to 0) exit 1) load new dataset, 2) change attribute or 3) change settings:\n", 0);
        }
    }

    private boolean parseBoolean(String prompt, boolean defaultValue) {
        console.printf(prompt, defaultValue);
        return Boolean.parseBoolean(console.readLine().trim());
    }

    private int parseInteger(String prompt, int defaultValue) {
        int parsed;
        try {
            console.printf(prompt, defaultValue);
            parsed = Integer.parseInt(console.readLine().trim());
        } catch (NumberFormatException ex) {
            parsed = defaultValue;
        }
        return parsed;
    }
}
